Chaerin.dev

[JS] Optional Chaining Utilization

Scenario šŸ¤Æ

The screen I was trying to create was as shown in the image above: when entering a new directory name in an input field and clicking the save button, the overlay on the card disappears, and a save screen should appear. However, after clicking the save button, the overlay disappeared but the save screen did not appear. The reason was that the event for removing the overlay when the input field loses focus happened before the event triggered when clicking the save button, preventing the save operation.

To address this, I modified the code as follows:

<ButtonWrap isShow={isShow} inputChange={inputChange}>
  <input
    className="addInput"
    placeholder="Enter a new directory name"
    onChange={(e) => {
      inputText.onChange(e)
      setInputChange(true)
    }}
    onFocus={(e) => {
      e.stopPropagation()
      setCardHoverInputState(true)
    }}
    onBlurCapture={(e) => {
      e.stopPropagation()
      console.log(e.relatedTarget.className)
      if (e.relatedTarget.className !== 'addBtn') {
        setCardHoverInputState(false)
      }
    }}
    value={inputText.value}
    maxLength={20}
    onKeyPress={onKeyPress}
  />
  <button className="addBtn" onClick={addDirHandler}>
    Save
  </button>
</ButtonWrap>

The overlay disappears only when the clicked componentā€™s className is not ā€œaddBtnā€, ensuring that it doesnā€™t disappear when clicking the save button. However, this approach caused an errorā€¦ šŸ˜‚ The issue arose because sometimes the clicked location was null, and accessing className on null caused an error.

In thinking about how to solve this, Optional Chaining came to mind.

Problem Resolution šŸ¤—

If the object before ?. is null or undefined, the evaluation stops and undefined is returned.

This is from my previous Optional Chaining posting. Optional chaining stops evaluation and returns undefined if the object being evaluated is null, avoiding errors.

By modifying e.relatedTarget.className to e?.relatedTarget?.className, even if the event target is null, it returns undefined instead of trying to access className on null, preventing errors.

I applied this to update the code:

<ButtonWrap isShow={isShow} inputChange={inputChange}>
  <input
    className="addInput"
    placeholder="Enter a new directory name"
    onChange={(e) => {
      inputText.onChange(e)
      setInputChange(true)
    }}
    onFocus={(e) => {
      e.stopPropagation()
      setCardHoverInputState(true)
    }}
    onBlurCapture={(e) => {
      e.stopPropagation()
      console.log(e?.relatedTarget?.className)
      if (e?.relatedTarget?.className !== 'addBtn') {
        setCardHoverInputState(false)
      }
    }}
    value={inputText.value}
    maxLength={20}
    onKeyPress={onKeyPress}
  />
  <button className="addBtn" onClick={addDirHandler}>
    Save
  </button>
</ButtonWrap>

Console Output Result

I confirmed that the optional chaining returned undefined, avoiding the error.

Reflection

Honestly, I hadnā€™t been able to use optional chaining much beyond receiving results from the server. This experience showed me how useful it can be in practical scenarios.

Without knowing optional chaining, I might have used ? : or && or structured if { ... } else { ... } to handle this situation. Using ?. is much cleaner and simpler, resulting in more elegant code!


Written by@Chaerin
Tech BlogšŸ“•

GitHubLinkedIn